package tech.abing.spider.task.crawler;

import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;

import tech.abing.spider.CrawTaskBuilder;
import tech.abing.spider.CrawlManager;
import tech.abing.spider.CrawlTask;
import tech.abing.spider.component.DynamicEntrance;
import tech.abing.spider.component.listener.TaskLifeListener;
import tech.abing.spider.constants.FinalConstants;
import tech.abing.spider.downloader.impl.DefaultPageDownloader;
import tech.abing.spider.request.PageRequest;
import tech.abing.spider.request.PageRequest.PageEncoding;
import tech.abing.spider.request.StartContext;
import tech.abing.spider.task.model.ProductID;
import tech.abing.spider.task.pageprocessor.TBProductPageProccessor1;
import tech.abing.spider.task.pageprocessor.TMProductPageProccessor1;
import tech.abing.spider.task.pipeline.ProductPipeline;
import tech.abing.spider.util.RedisUtil;
import tech.abing.spider.util.SysUtil;

public class ProductSpider {

	private static Logger logger = Logger.getLogger(ProductSpider.class);
	
	private static RedisUtil redisUtil = null;
	
	public void crawl(){
		this.crawl(10, 3, 500);//10线程，重试3次，礼貌访问间隔500ms
	}
	
	public void crawl(int threads){
		this.crawl(threads, 3, 500);//重试3次，礼貌访问间隔500ms
	}
	
	public void crawl(int threads, int retryCount){
		this.crawl(threads, retryCount, 500);//礼貌访问间隔500ms
	}
	
	public void crawl(int threads, int retryCount, int politenessDelay){
		CrawTaskBuilder builder = CrawlManager.getInstance()
				.prepareCrawlTask("根据任务表的产品ID抓取产品", DefaultPageDownloader.class)
				.useThread(threads)
				.useDynamicEntrance(RedisDynamicEntranceImpl.class)
				.usePageRetryCount(retryCount)
				.usePipeline(ProductPipeline.class)
				.usePageEncoding(PageEncoding.UTF8)
				.setPolitenessDelay(politenessDelay)
				.useTaskLifeListener(new TaskLifeListener() {
					
					@Override
					public void onStart(CrawlTask task) {
						
						if(redisUtil == null){
							redisUtil = RedisUtil.getInstance();
							logger.info("Redis连接池创建成功！");
						}
					}
					
					@Override
					public void onFinished(CrawlTask task) {
						
						task.getPipeline().destory();
						
						if(redisUtil != null){
							redisUtil.destroy();
							logger.info("Redis连接池关闭成功！");
						}
					}
				});
		
		CrawlTask spider = builder.build();
		
		CrawlManager.getInstance().start(spider);
	}
	
	/**
	 * 从Redis中取任务（产品ID）
	 * 
	 * @Description: TODO
	 * @author Ivan 2862099249@qq.com
	 * @date 2015年8月23日 上午11:49:17 
	 * @version V1.0
	 */
	public static final class RedisDynamicEntranceImpl extends DynamicEntrance {

		@Override
		public List<StartContext> loadStartContext() {
			StartContext context = new StartContext();
			String redisTask = SysUtil.getValue("redis.task_product_id");
			for(int i = 0; i < FinalConstants.REDIS_GET_PRODUCT_ID_FOR_PRODUCT; i++){
				
				try {
					int leaveNum = redisUtil.size(redisTask);
					
					logger.info("=========>Redis中还剩："+leaveNum);
					
					if(leaveNum == 0){
						break;//redis中的任务已经获取完，跳出循环
					}
					
					ProductID prodID = (ProductID) redisUtil.bpop(redisTask);
					
					String prodUrl = "https://item.taobao.com/item.htm?id="+prodID.getProdId();
					logger.info("=========>产品URL："+prodUrl);
					
					PageRequest req = null;
					if(FinalConstants.SHOP_TYPE_TAMLL.equals(prodID.getType())){
						req = context.createPageRequest(prodUrl, TMProductPageProccessor1.class, 0);
					}else if(FinalConstants.SHOP_TYPE_TAOBAO.equals(prodID.getType())){
						req = context.createPageRequest(prodUrl, TBProductPageProccessor1.class, 0);
					}
					
					if(req != null){
						req.putParams("shopId", prodID.getShopId());
						req.putParams("saleCount", prodID.getSaleCount());
						req.putParams("itemId", prodID.getProdId());
						req.putParams("shopType", prodID.getType());
						
						context.injectSeed(req);
					}
					
				} catch (InterruptedException e) {
					e.printStackTrace();
					logger.error("Redis出队["+redisTask+"]被中断", e);
				}
				
			}
			
			return Arrays.asList(context);
		}
		
		@Override
		public boolean continueLoad() {
			return true;//循环采集
		}

	}
}
